package com.lxq.cloud.ai.controller;

import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioTranscriptionOptions;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisPrompt;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisResponse;
import com.alibaba.cloud.ai.dashscope.audio.transcription.AudioTranscriptionModel;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import org.springframework.core.io.UrlResource;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.audio.transcription.AudioTranscriptionPrompt;
import org.springframework.ai.audio.transcription.AudioTranscriptionResponse;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.ChatClient.Builder;
import org.springframework.ai.image.ImageModel;
import org.springframework.ai.image.ImageOptions;
import org.springframework.ai.image.ImageOptionsBuilder;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import org.springframework.core.io.UrlResource;
@RestController
@Slf4j
public class SimpleAiController {
    private static final String FILE_PATH = "spring-ai-alibaba-audio-example/dashscope-audio/src/main/resources/gen/tts";

    private final ChatClient chatClient;
//    private final OpenAiChatModel chatModel;
    private final ImageModel imageClient;
//    private final OpenAiAudioTranscriptionModel audioClient;
//    private final OpenAiAudioSpeechModel openAiAudioSpeechModel;
private final AudioTranscriptionModel transcriptionModel;
    private final SpeechSynthesisModel speechSynthesisModel;
    @Autowired
    public SimpleAiController(Builder chatClientBuilder,ImageModel imageClient,AudioTranscriptionModel transcriptionModel,SpeechSynthesisModel speechSynthesisModel) {
        this.chatClient = chatClientBuilder.build();
//        this.chatModel = chatModel;
        this.imageClient = imageClient;
       this.speechSynthesisModel = speechSynthesisModel;
       this.transcriptionModel = transcriptionModel;
    }


    @Value("${AI_KEY_OPENAI}")
    private String openAiKey;


    /* 智能对话 演示
     * OpenAI：
     * @see  https://docs.spring.io/spring-ai/reference/1.0/api/chatclient.html#_returning_a_chatresponse
     *
     * 中转方式有一定几率出错
     * */
    @GetMapping("/ai/simple")
    public Map<String, String> completion(@RequestParam(value = "message", defaultValue = "给我讲个笑话") String message) {
        log.info(openAiKey);
        var value = chatClient.prompt()

                .user(message).call().content();

        return Map.of("generation", value);
    }

    /* 流式响应 演示
     * OpenAI：
     * @see  https://docs.spring.io/spring-ai/reference/1.0/api/chatclient.html#_streaming_responses
     *
     * 中转方式不行就换openai
     * */
    @GetMapping(value = "/ai/stream", produces = "text/sse;charset=UTF-8")
    public Flux<String> stream(@RequestParam(value = "message", defaultValue = "给我讲个笑话") String message) {
        log.info(openAiKey);
        return chatClient.prompt()
                .user(message)
                .stream()
                .content();
    }


    /* 文生图 演示
     * OpenAI： 目前只有 dall-e-3 和 dall-e-2（更笨且支持更小尺寸） 模型可用
     * @see  https://docs.spring.io/spring-ai/reference/1.0/api/image/openai-image.html#image-options
     *       https://platform.openai.com/docs/api-reference/images
     * 中转方式不行就换openai
     * */
    @GetMapping(value = "/ai/img", produces = "text/html")
    public String image(@RequestParam(value = "message", defaultValue = "猫") String message) throws IOException {
        ImageOptions options = ImageOptionsBuilder.builder().model("wanx-v1")
                //.withQuality("hd")
                .N(1) .height(1024)
                .width(1024)
        .build();
        ImageResponse response = imageClient.call(
                new ImagePrompt(message,
                        options));

        String url = response.getResult().getOutput().getUrl();
        log.info(url);

        return "<img src='" + url + "'/>";

    }
    private static final String AUDIO_RESOURCES_URL = "https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav";

    private static final String DEFAULT_MODEL_1 = "sensevoice-v1";
    /* 语音转文本  演示
     * OpenAI： 只有whisper-1模型可用
     * @see  https://docs.spring.io/spring-ai/reference/1.0/api/audio/transcriptions/openai-transcriptions.html
     * 		 https://platform.openai.com/docs/api-reference/audio/createTranscription
     * 中转方式不行就换openai
     * */
    @GetMapping(value = "/ai/audio2text")
    public String audio2text() throws MalformedURLException {
        AudioTranscriptionResponse response = transcriptionModel.call(
                new AudioTranscriptionPrompt(
                        new UrlResource(AUDIO_RESOURCES_URL),
                        new DashScopeAudioTranscriptionOptionsAdapter(
                                DashScopeAudioTranscriptionOptions.builder()
                                        .withModel(DEFAULT_MODEL_1)
                                        .build()
                        )
                )
        );

        return response.getResult().getOutput();



//        var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
//                .responseFormat(OpenAiAudioApi.TranscriptResponseFormat.TEXT)
//                .temperature(0f)
//                // 默认
//                .model(OpenAiAudioApi.WhisperModel.WHISPER_1.getValue())
//                .build();
//
//        // flac、mp3、mp4、mpeg、mpga、m4a、ogg、wav 或 webm。
//        var audioFile = new ClassPathResource("/hello.mp3");
//
//        AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
//        AudioTranscriptionResponse response = audioClient.call(transcriptionRequest);
//
//        //openAiAudioApi.createTranscription()
//        return response.getResult().getOutput();
    }


    /* 文转语音  演示
     * OpenAI： 目前只有 tts-1 模型可用
     * @see https://docs.spring.io/spring-ai/reference/1.0/api/audio/speech/openai-speech.html
     * 		https://platform.openai.com/docs/api-reference/audio/createSpeech
     * 中转方式不行就换openai
     * */
    @GetMapping(value = "/ai/text2audio")
    public String text2audit(String text) {
        Flux<SpeechSynthesisResponse> response = speechSynthesisModel.stream(
                new SpeechSynthesisPrompt(text)
        );
     //   byte[] body=null;
        CountDownLatch latch = new CountDownLatch(1);
        File file = new File(FILE_PATH + "/output-stream.mp3");
        try (FileOutputStream fos = new FileOutputStream(file)) {

            response.doFinally(
                    signal -> latch.countDown()
            ).subscribe(synthesisResponse -> {
                ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
                byte[]  body = new byte[byteBuffer.remaining()];
                byteBuffer.get(body);
                try {
                    fos.write(body);
                }
                catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });

            latch.await();
        }
        catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }




//        OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
//                .model(OpenAiAudioApi.TtsModel.TTS_1.value)
//                .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
//                .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
//                .speed(1.0f)
//                .build();
//
//        SpeechPrompt speechPrompt = new SpeechPrompt("Hello, 大家好我是徐庶", speechOptions);
//        SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
//
//        byte[] body = response.getResult().getOutput();


        // 将byte[]存为 mp3文件
//        try {
//            writeByteArrayToMp3(body, System.getProperty("user.dir"));
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        return "ok";
    }

//    public static void writeByteArrayToMp3(byte[] audioBytes, String outputFilePath) throws IOException {
    ////        // 创建FileOutputStream实例
    ////        FileOutputStream fos = new FileOutputStream(outputFilePath + "/xushu.mp3");
    ////
    ////        // 将字节数组写入文件
    ////        fos.write(audioBytes);
    ////
    ////        // 关闭文件输出流
    ////        fos.close();
    ////    }


    /*多模态  演示
     * OpenAI： gpt-4-visual-preview 和 gpt-4o 模型提供多模式支持
     * @see https://docs.spring.io/spring-ai/reference/1.0/api/chat/openai-chat.html#_multimodal
     * 中转方式不行就换openai（需要有4的权限）
     * */
    @GetMapping(value = "/ai/mutil")
    public String mutilModel(@RequestParam(value = "message", defaultValue = "你从这个图片中看到了什么？") String message) throws IOException {

//        byte[] imageData = new ClassPathResource("/test.png").getContentAsByteArray();
//
//
//        var userMessage = new UserMessage(
//                message, // content
//                List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData))); // media
//
//        ChatResponse response = chatModel.call(new Prompt(userMessage,
//                OpenAiChatOptions.builder()
//                        .model(OpenAiApi.ChatModel.GPT_4_TURBO_PREVIEW.getValue())
//                        .build()));
//
//        return response.getResult().getOutput().content();
        return "";
    }


}
